{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "source": [
        "!pip install openai-agents python-dotenv\n",
        "\n",
        "import asyncio\n",
        "import json\n",
        "from datetime import datetime\n",
        "from agents import Agent, Runner, function_tool, SQLiteSession\n",
        "import os\n",
        "\n",
        "os.environ['OPENAI_API_KEY'] = 'Use Your Own API Key'"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "HaVqG9_y8HE9",
        "outputId": "7fcfb4cb-152c-4b65-980c-c43c95a9bd5a"
      },
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Collecting openai-agents\n",
            "  Downloading openai_agents-0.2.4-py3-none-any.whl.metadata (11 kB)\n",
            "Collecting python-dotenv\n",
            "  Downloading python_dotenv-1.1.1-py3-none-any.whl.metadata (24 kB)\n",
            "Collecting griffe<2,>=1.5.6 (from openai-agents)\n",
            "  Downloading griffe-1.11.0-py3-none-any.whl.metadata (5.0 kB)\n",
            "Collecting mcp<2,>=1.11.0 (from openai-agents)\n",
            "  Downloading mcp-1.12.3-py3-none-any.whl.metadata (60 kB)\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m61.0/61.0 kB\u001b[0m \u001b[31m3.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25hRequirement already satisfied: openai<2,>=1.97.1 in /usr/local/lib/python3.11/dist-packages (from openai-agents) (1.98.0)\n",
            "Requirement already satisfied: pydantic<3,>=2.10 in /usr/local/lib/python3.11/dist-packages (from openai-agents) (2.11.7)\n",
            "Requirement already satisfied: requests<3,>=2.0 in /usr/local/lib/python3.11/dist-packages (from openai-agents) (2.32.3)\n",
            "Collecting types-requests<3,>=2.0 (from openai-agents)\n",
            "  Downloading types_requests-2.32.4.20250611-py3-none-any.whl.metadata (2.1 kB)\n",
            "Requirement already satisfied: typing-extensions<5,>=4.12.2 in /usr/local/lib/python3.11/dist-packages (from openai-agents) (4.14.1)\n",
            "Collecting colorama>=0.4 (from griffe<2,>=1.5.6->openai-agents)\n",
            "  Downloading colorama-0.4.6-py2.py3-none-any.whl.metadata (17 kB)\n",
            "Requirement already satisfied: anyio>=4.5 in /usr/local/lib/python3.11/dist-packages (from mcp<2,>=1.11.0->openai-agents) (4.10.0)\n",
            "Collecting httpx-sse>=0.4 (from mcp<2,>=1.11.0->openai-agents)\n",
            "  Downloading httpx_sse-0.4.1-py3-none-any.whl.metadata (9.4 kB)\n",
            "Requirement already satisfied: httpx>=0.27 in /usr/local/lib/python3.11/dist-packages (from mcp<2,>=1.11.0->openai-agents) (0.28.1)\n",
            "Requirement already satisfied: jsonschema>=4.20.0 in /usr/local/lib/python3.11/dist-packages (from mcp<2,>=1.11.0->openai-agents) (4.25.0)\n",
            "Collecting pydantic-settings>=2.5.2 (from mcp<2,>=1.11.0->openai-agents)\n",
            "  Downloading pydantic_settings-2.10.1-py3-none-any.whl.metadata (3.4 kB)\n",
            "Requirement already satisfied: python-multipart>=0.0.9 in /usr/local/lib/python3.11/dist-packages (from mcp<2,>=1.11.0->openai-agents) (0.0.20)\n",
            "Collecting sse-starlette>=1.6.1 (from mcp<2,>=1.11.0->openai-agents)\n",
            "  Downloading sse_starlette-3.0.2-py3-none-any.whl.metadata (11 kB)\n",
            "Requirement already satisfied: starlette>=0.27 in /usr/local/lib/python3.11/dist-packages (from mcp<2,>=1.11.0->openai-agents) (0.47.2)\n",
            "Requirement already satisfied: uvicorn>=0.23.1 in /usr/local/lib/python3.11/dist-packages (from mcp<2,>=1.11.0->openai-agents) (0.35.0)\n",
            "Requirement already satisfied: distro<2,>=1.7.0 in /usr/local/lib/python3.11/dist-packages (from openai<2,>=1.97.1->openai-agents) (1.9.0)\n",
            "Requirement already satisfied: jiter<1,>=0.4.0 in /usr/local/lib/python3.11/dist-packages (from openai<2,>=1.97.1->openai-agents) (0.10.0)\n",
            "Requirement already satisfied: sniffio in /usr/local/lib/python3.11/dist-packages (from openai<2,>=1.97.1->openai-agents) (1.3.1)\n",
            "Requirement already satisfied: tqdm>4 in /usr/local/lib/python3.11/dist-packages (from openai<2,>=1.97.1->openai-agents) (4.67.1)\n",
            "Requirement already satisfied: annotated-types>=0.6.0 in /usr/local/lib/python3.11/dist-packages (from pydantic<3,>=2.10->openai-agents) (0.7.0)\n",
            "Requirement already satisfied: pydantic-core==2.33.2 in /usr/local/lib/python3.11/dist-packages (from pydantic<3,>=2.10->openai-agents) (2.33.2)\n",
            "Requirement already satisfied: typing-inspection>=0.4.0 in /usr/local/lib/python3.11/dist-packages (from pydantic<3,>=2.10->openai-agents) (0.4.1)\n",
            "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.11/dist-packages (from requests<3,>=2.0->openai-agents) (3.4.2)\n",
            "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.11/dist-packages (from requests<3,>=2.0->openai-agents) (3.10)\n",
            "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.11/dist-packages (from requests<3,>=2.0->openai-agents) (2.5.0)\n",
            "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.11/dist-packages (from requests<3,>=2.0->openai-agents) (2025.8.3)\n",
            "Requirement already satisfied: httpcore==1.* in /usr/local/lib/python3.11/dist-packages (from httpx>=0.27->mcp<2,>=1.11.0->openai-agents) (1.0.9)\n",
            "Requirement already satisfied: h11>=0.16 in /usr/local/lib/python3.11/dist-packages (from httpcore==1.*->httpx>=0.27->mcp<2,>=1.11.0->openai-agents) (0.16.0)\n",
            "Requirement already satisfied: attrs>=22.2.0 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=4.20.0->mcp<2,>=1.11.0->openai-agents) (25.3.0)\n",
            "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=4.20.0->mcp<2,>=1.11.0->openai-agents) (2025.4.1)\n",
            "Requirement already satisfied: referencing>=0.28.4 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=4.20.0->mcp<2,>=1.11.0->openai-agents) (0.36.2)\n",
            "Requirement already satisfied: rpds-py>=0.7.1 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=4.20.0->mcp<2,>=1.11.0->openai-agents) (0.26.0)\n",
            "Requirement already satisfied: click>=7.0 in /usr/local/lib/python3.11/dist-packages (from uvicorn>=0.23.1->mcp<2,>=1.11.0->openai-agents) (8.2.1)\n",
            "Downloading openai_agents-0.2.4-py3-none-any.whl (164 kB)\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m164.3/164.3 kB\u001b[0m \u001b[31m7.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25hDownloading python_dotenv-1.1.1-py3-none-any.whl (20 kB)\n",
            "Downloading griffe-1.11.0-py3-none-any.whl (137 kB)\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m137.6/137.6 kB\u001b[0m \u001b[31m12.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25hDownloading mcp-1.12.3-py3-none-any.whl (158 kB)\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m158.8/158.8 kB\u001b[0m \u001b[31m9.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25hDownloading types_requests-2.32.4.20250611-py3-none-any.whl (20 kB)\n",
            "Downloading colorama-0.4.6-py2.py3-none-any.whl (25 kB)\n",
            "Downloading httpx_sse-0.4.1-py3-none-any.whl (8.1 kB)\n",
            "Downloading pydantic_settings-2.10.1-py3-none-any.whl (45 kB)\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m45.2/45.2 kB\u001b[0m \u001b[31m3.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25hDownloading sse_starlette-3.0.2-py3-none-any.whl (11 kB)\n",
            "Installing collected packages: types-requests, python-dotenv, httpx-sse, colorama, sse-starlette, griffe, pydantic-settings, mcp, openai-agents\n",
            "Successfully installed colorama-0.4.6 griffe-1.11.0 httpx-sse-0.4.1 mcp-1.12.3 openai-agents-0.2.4 pydantic-settings-2.10.1 python-dotenv-1.1.1 sse-starlette-3.0.2 types-requests-2.32.4.20250611\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "@function_tool\n",
        "def web_search(query: str, max_results: int = 3) -> str:\n",
        "    \"\"\"Simulate web search results for demonstration\"\"\"\n",
        "    results = [\n",
        "        f\"Result 1 for '{query}': Latest findings show significant developments...\",\n",
        "        f\"Result 2 for '{query}': Research indicates new approaches in this field...\",\n",
        "        f\"Result 3 for '{query}': Expert analysis suggests important implications...\"\n",
        "    ]\n",
        "    return f\"Search results for '{query}':\\n\" + \"\\n\".join(results[:max_results])\n",
        "\n",
        "@function_tool\n",
        "def analyze_data(data: str, analysis_type: str = \"summary\") -> str:\n",
        "    \"\"\"Analyze provided data with different analysis types\"\"\"\n",
        "    analyses = {\n",
        "        \"summary\": f\"Summary: The data contains {len(data.split())} key points with main themes around innovation and efficiency.\",\n",
        "        \"detailed\": f\"Detailed Analysis: Breaking down the {len(data)} characters of data reveals patterns in methodology and conclusions.\",\n",
        "        \"trends\": f\"Trend Analysis: Current data suggests upward trajectory with 3 major inflection points identified.\"\n",
        "    }\n",
        "    return analyses.get(analysis_type, \"Analysis complete: Standard evaluation performed.\")\n",
        "\n",
        "@function_tool\n",
        "def save_research(title: str, content: str, category: str = \"general\") -> str:\n",
        "    \"\"\"Save research findings to a structured format\"\"\"\n",
        "    timestamp = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n",
        "    research_entry = {\n",
        "        \"title\": title,\n",
        "        \"content\": content,\n",
        "        \"category\": category,\n",
        "        \"timestamp\": timestamp,\n",
        "        \"id\": f\"research_{len(content) % 1000}\"\n",
        "    }\n",
        "    return f\"✅ Research saved: '{title}' in category '{category}' at {timestamp}\""
      ],
      "metadata": {
        "id": "wc6UegNO9Z8y"
      },
      "execution_count": 3,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "research_agent = Agent(\n",
        "    name=\"Research Specialist\",\n",
        "    instructions=\"\"\"You are an expert researcher who:\n",
        "    - Conducts thorough web searches on any topic\n",
        "    - Analyzes information critically and objectively\n",
        "    - Identifies key insights and patterns\n",
        "    - Always uses tools to gather and analyze data before responding\"\"\",\n",
        "    tools=[web_search, analyze_data]\n",
        ")\n",
        "\n",
        "analyst_agent = Agent(\n",
        "    name=\"Data Analyst\",\n",
        "    instructions=\"\"\"You are a senior data analyst who:\n",
        "    - Takes research findings and performs deep analysis\n",
        "    - Identifies trends, patterns, and actionable insights\n",
        "    - Creates structured summaries and recommendations\n",
        "    - Uses analysis tools to enhance understanding\"\"\",\n",
        "    tools=[analyze_data, save_research]\n",
        ")\n",
        "\n",
        "coordinator_agent = Agent(\n",
        "    name=\"Research Coordinator\",\n",
        "    instructions=\"\"\"You are a research coordinator who:\n",
        "    - Manages multi-step research projects\n",
        "    - Delegates tasks to appropriate specialists\n",
        "    - Synthesizes findings from multiple sources\n",
        "    - Makes final decisions on research direction\n",
        "    - Handoff to research_agent for initial data gathering\n",
        "    - Handoff to analyst_agent for detailed analysis\"\"\",\n",
        "    handoffs=[research_agent, analyst_agent],\n",
        "    tools=[save_research]\n",
        ")"
      ],
      "metadata": {
        "id": "4s46YmuQ9gcI"
      },
      "execution_count": 4,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "async def run_advanced_research_workflow():\n",
        "    \"\"\"Demonstrates a complete multi-agent research workflow\"\"\"\n",
        "\n",
        "    session = SQLiteSession(\"research_session_001\")\n",
        "\n",
        "    print(\"🚀 Starting Advanced Multi-Agent Research System\")\n",
        "    print(\"=\" * 60)\n",
        "\n",
        "    research_topic = \"artificial intelligence in healthcare 2024\"\n",
        "\n",
        "    print(f\"\\n📋 PHASE 1: Initiating research on '{research_topic}'\")\n",
        "    result1 = await Runner.run(\n",
        "        coordinator_agent,\n",
        "        f\"I need comprehensive research on '{research_topic}'. Please coordinate a full research workflow including data gathering, analysis, and final report generation.\",\n",
        "        session=session\n",
        "    )\n",
        "    print(f\"Coordinator Response: {result1.final_output}\")\n",
        "\n",
        "    print(f\"\\n📊 PHASE 2: Requesting detailed trend analysis\")\n",
        "    result2 = await Runner.run(\n",
        "        coordinator_agent,\n",
        "        \"Based on the previous research, I need a detailed trend analysis focusing on emerging opportunities and potential challenges. Save the final analysis for future reference.\",\n",
        "        session=session\n",
        "    )\n",
        "    print(f\"Analysis Response: {result2.final_output}\")\n",
        "\n",
        "    print(f\"\\n🔬 PHASE 3: Direct specialist analysis\")\n",
        "    result3 = await Runner.run(\n",
        "        analyst_agent,\n",
        "        \"Perform a detailed analysis of the healthcare AI market, focusing on regulatory challenges and market opportunities. Categorize this as 'market_analysis'.\",\n",
        "        session=session\n",
        "    )\n",
        "    print(f\"Specialist Response: {result3.final_output}\")\n",
        "\n",
        "    print(\"\\n✅ Research workflow completed successfully!\")\n",
        "    return result1, result2, result3\n",
        "\n",
        "async def run_focused_analysis():\n",
        "    \"\"\"Shows focused single-agent capabilities\"\"\"\n",
        "\n",
        "    print(\"\\n🎯 FOCUSED ANALYSIS DEMO\")\n",
        "    print(\"-\" * 40)\n",
        "\n",
        "    result = await Runner.run(\n",
        "        research_agent,\n",
        "        \"Research the latest developments in quantum computing and analyze the key breakthroughs from 2024.\",\n",
        "        max_turns=5\n",
        "    )\n",
        "\n",
        "    print(f\"Focused Analysis Result: {result.final_output}\")\n",
        "    return result\n",
        "\n",
        "def quick_research_sync(topic: str):\n",
        "    \"\"\"Synchronous research for quick queries\"\"\"\n",
        "\n",
        "    print(f\"\\n⚡ QUICK SYNC RESEARCH: {topic}\")\n",
        "    print(\"-\" * 40)\n",
        "\n",
        "    result = Runner.run_sync(\n",
        "        research_agent,\n",
        "        f\"Quickly research {topic} and provide 3 key insights.\"\n",
        "    )\n",
        "\n",
        "    print(f\"Quick Result: {result.final_output}\")\n",
        "    return result"
      ],
      "metadata": {
        "id": "ziZOimHZ9kVU"
      },
      "execution_count": 5,
      "outputs": []
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 705
        },
        "id": "OPbleuN17toN",
        "outputId": "803db770-80df-4b5f-cd27-3fe0d50da4b3"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "🤖 OpenAI Agents SDK - Advanced Tutorial\n",
            "Building a Multi-Agent Research System\n",
            "============================================================\n",
            "🚀 Starting Advanced Multi-Agent Research System\n",
            "============================================================\n",
            "\n",
            "📋 PHASE 1: Initiating research on 'artificial intelligence in healthcare 2024'\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "ERROR:openai.agents:Error getting response: Error code: 429 - {'error': {'message': 'You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.', 'type': 'insufficient_quota', 'param': None, 'code': 'insufficient_quota'}}. (request_id: req_5ce06a60afea34921b983b4a95a98a9c)\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "❌ Error: Error code: 429 - {'error': {'message': 'You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.', 'type': 'insufficient_quota', 'param': None, 'code': 'insufficient_quota'}}\n",
            "\n",
            "Troubleshooting tips:\n",
            "- Ensure OPENAI_API_KEY is set correctly\n",
            "- Check internet connection\n",
            "- Verify openai-agents package is installed\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "ERROR:openai.agents:Error getting response: Error code: 429 - {'error': {'message': 'You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.', 'type': 'insufficient_quota', 'param': None, 'code': 'insufficient_quota'}}. (request_id: req_d267525bc75190cc8e801b6f4def28c5)\n"
          ]
        },
        {
          "output_type": "error",
          "ename": "RateLimitError",
          "evalue": "Error code: 429 - {'error': {'message': 'You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.', 'type': 'insufficient_quota', 'param': None, 'code': 'insufficient_quota'}}",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mRateLimitError\u001b[0m                            Traceback (most recent call last)",
            "\u001b[0;32m/tmp/ipython-input-2848730247.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     44\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     45\u001b[0m \u001b[0mcustom_agent\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcreate_custom_agent\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Code Reviewer\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"senior software engineer\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0manalyze_data\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 46\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mRunner\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_sync\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcustom_agent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"Review this Python code for best practices\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     47\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     48\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"\\n📚 Tutorial Notes:\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/agents/run.py\u001b[0m in \u001b[0;36mrun_sync\u001b[0;34m(cls, starting_agent, input, context, max_turns, hooks, run_config, previous_response_id, session)\u001b[0m\n\u001b[1;32m    258\u001b[0m         \"\"\"\n\u001b[1;32m    259\u001b[0m         \u001b[0mrunner\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mDEFAULT_AGENT_RUNNER\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 260\u001b[0;31m         return runner.run_sync(\n\u001b[0m\u001b[1;32m    261\u001b[0m             \u001b[0mstarting_agent\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    262\u001b[0m             \u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/agents/run.py\u001b[0m in \u001b[0;36mrun_sync\u001b[0;34m(self, starting_agent, input, **kwargs)\u001b[0m\n\u001b[1;32m    511\u001b[0m         \u001b[0msession\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"session\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    512\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 513\u001b[0;31m         return asyncio.get_event_loop().run_until_complete(\n\u001b[0m\u001b[1;32m    514\u001b[0m             self.run(\n\u001b[1;32m    515\u001b[0m                 \u001b[0mstarting_agent\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/nest_asyncio.py\u001b[0m in \u001b[0;36mrun_until_complete\u001b[0;34m(self, future)\u001b[0m\n\u001b[1;32m     96\u001b[0m                 raise RuntimeError(\n\u001b[1;32m     97\u001b[0m                     'Event loop stopped before Future completed.')\n\u001b[0;32m---> 98\u001b[0;31m             \u001b[0;32mreturn\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     99\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    100\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m_run_once\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/lib/python3.11/asyncio/futures.py\u001b[0m in \u001b[0;36mresult\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    201\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__log_traceback\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    202\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_exception\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 203\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_exception\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwith_traceback\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_exception_tb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    204\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_result\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    205\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/lib/python3.11/asyncio/tasks.py\u001b[0m in \u001b[0;36m__step\u001b[0;34m(***failed resolving arguments***)\u001b[0m\n\u001b[1;32m    277\u001b[0m                 \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    278\u001b[0m             \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 279\u001b[0;31m                 \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mthrow\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    280\u001b[0m         \u001b[0;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mexc\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    281\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_must_cancel\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/agents/run.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, starting_agent, input, **kwargs)\u001b[0m\n\u001b[1;32m    410\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    411\u001b[0m                     \u001b[0;32mif\u001b[0m \u001b[0mcurrent_turn\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 412\u001b[0;31m                         input_guardrail_results, turn_result = await asyncio.gather(\n\u001b[0m\u001b[1;32m    413\u001b[0m                             self._run_input_guardrails(\n\u001b[1;32m    414\u001b[0m                                 \u001b[0mstarting_agent\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/lib/python3.11/asyncio/tasks.py\u001b[0m in \u001b[0;36m__wakeup\u001b[0;34m(self, future)\u001b[0m\n\u001b[1;32m    347\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m__wakeup\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfuture\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    348\u001b[0m         \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 349\u001b[0;31m             \u001b[0mfuture\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    350\u001b[0m         \u001b[0;32mexcept\u001b[0m \u001b[0mBaseException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mexc\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    351\u001b[0m             \u001b[0;31m# This may also be a cancellation.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/lib/python3.11/asyncio/tasks.py\u001b[0m in \u001b[0;36m__step\u001b[0;34m(***failed resolving arguments***)\u001b[0m\n\u001b[1;32m    275\u001b[0m                 \u001b[0;31m# We use the `send` method directly, because coroutines\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    276\u001b[0m                 \u001b[0;31m# don't have `__iter__` and `__next__` methods.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 277\u001b[0;31m                 \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    278\u001b[0m             \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    279\u001b[0m                 \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcoro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mthrow\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/agents/run.py\u001b[0m in \u001b[0;36m_run_single_turn\u001b[0;34m(cls, agent, all_tools, original_input, generated_items, hooks, context_wrapper, run_config, should_run_agent_start_hooks, tool_use_tracker, previous_response_id)\u001b[0m\n\u001b[1;32m    958\u001b[0m         \u001b[0minput\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mextend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mgenerated_item\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_input_item\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mgenerated_item\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mgenerated_items\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    959\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 960\u001b[0;31m         new_response = await cls._get_new_response(\n\u001b[0m\u001b[1;32m    961\u001b[0m             \u001b[0magent\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    962\u001b[0m             \u001b[0msystem_prompt\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/agents/run.py\u001b[0m in \u001b[0;36m_get_new_response\u001b[0;34m(cls, agent, system_prompt, input, output_schema, all_tools, handoffs, context_wrapper, run_config, tool_use_tracker, previous_response_id, prompt_config)\u001b[0m\n\u001b[1;32m   1119\u001b[0m         \u001b[0mmodel_settings\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mRunImpl\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmaybe_reset_tool_choice\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0magent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtool_use_tracker\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmodel_settings\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1120\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1121\u001b[0;31m         new_response = await model.get_response(\n\u001b[0m\u001b[1;32m   1122\u001b[0m             \u001b[0msystem_instructions\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msystem_prompt\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1123\u001b[0m             \u001b[0minput\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/agents/models/openai_responses.py\u001b[0m in \u001b[0;36mget_response\u001b[0;34m(self, system_instructions, input, model_settings, tools, output_schema, handoffs, tracing, previous_response_id, prompt)\u001b[0m\n\u001b[1;32m     81\u001b[0m         \u001b[0;32mwith\u001b[0m \u001b[0mresponse_span\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdisabled\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtracing\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_disabled\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mspan_response\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     82\u001b[0m             \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 83\u001b[0;31m                 response = await self._fetch_response(\n\u001b[0m\u001b[1;32m     84\u001b[0m                     \u001b[0msystem_instructions\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     85\u001b[0m                     \u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/agents/models/openai_responses.py\u001b[0m in \u001b[0;36m_fetch_response\u001b[0;34m(self, system_instructions, input, model_settings, tools, output_schema, handoffs, previous_response_id, stream, prompt)\u001b[0m\n\u001b[1;32m    265\u001b[0m             )\n\u001b[1;32m    266\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 267\u001b[0;31m         return await self._client.responses.create(\n\u001b[0m\u001b[1;32m    268\u001b[0m             \u001b[0mprevious_response_id\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_non_null_or_not_given\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprevious_response_id\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    269\u001b[0m             \u001b[0minstructions\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_non_null_or_not_given\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msystem_instructions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/openai/resources/responses/responses.py\u001b[0m in \u001b[0;36mcreate\u001b[0;34m(self, background, include, input, instructions, max_output_tokens, max_tool_calls, metadata, model, parallel_tool_calls, previous_response_id, prompt, prompt_cache_key, reasoning, safety_identifier, service_tier, store, stream, temperature, text, tool_choice, tools, top_logprobs, top_p, truncation, user, extra_headers, extra_query, extra_body, timeout)\u001b[0m\n\u001b[1;32m   2088\u001b[0m         \u001b[0mtimeout\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mfloat\u001b[0m \u001b[0;34m|\u001b[0m \u001b[0mhttpx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTimeout\u001b[0m \u001b[0;34m|\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;34m|\u001b[0m \u001b[0mNotGiven\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mNOT_GIVEN\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2089\u001b[0m     ) -> Response | AsyncStream[ResponseStreamEvent]:\n\u001b[0;32m-> 2090\u001b[0;31m         return await self._post(\n\u001b[0m\u001b[1;32m   2091\u001b[0m             \u001b[0;34m\"/responses\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2092\u001b[0m             body=await async_maybe_transform(\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/openai/_base_client.py\u001b[0m in \u001b[0;36mpost\u001b[0;34m(self, path, cast_to, body, files, options, stream, stream_cls)\u001b[0m\n\u001b[1;32m   1789\u001b[0m             \u001b[0mmethod\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"post\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mjson_data\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mbody\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfiles\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mawait\u001b[0m \u001b[0masync_to_httpx_files\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfiles\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0moptions\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1790\u001b[0m         )\n\u001b[0;32m-> 1791\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0;32mawait\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcast_to\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mopts\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstream\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mstream\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstream_cls\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mstream_cls\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1792\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1793\u001b[0m     async def patch(\n",
            "\u001b[0;32m/usr/local/lib/python3.11/dist-packages/openai/_base_client.py\u001b[0m in \u001b[0;36mrequest\u001b[0;34m(self, cast_to, options, stream, stream_cls)\u001b[0m\n\u001b[1;32m   1589\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1590\u001b[0m                 \u001b[0mlog\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdebug\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Re-raising status error\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1591\u001b[0;31m                 \u001b[0;32mraise\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_make_status_error_from_response\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresponse\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1592\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1593\u001b[0m             \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;31mRateLimitError\u001b[0m: Error code: 429 - {'error': {'message': 'You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.', 'type': 'insufficient_quota', 'param': None, 'code': 'insufficient_quota'}}"
          ]
        }
      ],
      "source": [
        "async def main():\n",
        "    \"\"\"Main function demonstrating all capabilities\"\"\"\n",
        "\n",
        "    print(\"🤖 OpenAI Agents SDK - Advanced Tutorial\")\n",
        "    print(\"Building a Multi-Agent Research System\")\n",
        "    print(\"=\" * 60)\n",
        "\n",
        "    try:\n",
        "        await run_advanced_research_workflow()\n",
        "\n",
        "        await run_focused_analysis()\n",
        "\n",
        "        quick_research_sync(\"blockchain adoption in enterprise\")\n",
        "\n",
        "        print(\"\\n🎉 Tutorial completed successfully!\")\n",
        "        print(\"\\nKey Features Demonstrated:\")\n",
        "        print(\"✅ Multi-agent coordination with handoffs\")\n",
        "        print(\"✅ Custom function tools\")\n",
        "        print(\"✅ Session memory for conversation continuity\")\n",
        "        print(\"✅ Async and sync execution patterns\")\n",
        "        print(\"✅ Structured workflows with max_turns control\")\n",
        "        print(\"✅ Specialized agent roles and capabilities\")\n",
        "\n",
        "    except Exception as e:\n",
        "        print(f\"❌ Error: {e}\")\n",
        "        print(\"\\nTroubleshooting tips:\")\n",
        "        print(\"- Ensure OPENAI_API_KEY is set correctly\")\n",
        "        print(\"- Check internet connection\")\n",
        "        print(\"- Verify openai-agents package is installed\")\n",
        "\n",
        "if __name__ == \"__main__\":\n",
        "    import nest_asyncio\n",
        "    nest_asyncio.apply()\n",
        "\n",
        "    asyncio.run(main())\n",
        "\n",
        "def create_custom_agent(name: str, role: str, tools_list: list = None):\n",
        "    \"\"\"Helper function to create custom agents quickly\"\"\"\n",
        "    return Agent(\n",
        "        name=name,\n",
        "        instructions=f\"You are a {role} who provides expert assistance.\",\n",
        "        tools=tools_list or []\n",
        "    )\n",
        "\n",
        "custom_agent = create_custom_agent(\"Code Reviewer\", \"senior software engineer\", [analyze_data])\n",
        "result = Runner.run_sync(custom_agent, \"Review this Python code for best practices\")\n",
        "\n",
        "print(\"\\n📚 Tutorial Notes:\")\n",
        "print(\"- Modify research topics and agent instructions to explore different use cases\")\n",
        "print(\"- Add your own custom tools using the @function_tool decorator\")\n",
        "print(\"- Experiment with different agent handoff patterns\")\n",
        "print(\"- Use sessions for multi-turn conversations\")\n",
        "print(\"- Perfect for Colab - just add your OpenAI API key and run!\")"
      ]
    }
  ]
}